package com.wuchao.reflectandanno;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
 * 作者：吴超
 * 邮箱：wuchao_19931120@163.com
 * 时间：2021-11-14
 * 描述：1. 反射：其实就是动态获取类的信息，从而创建对象。比如：可以把类名写在配置文件里，通过读取配置文件，获得类名，进行反射，从而创建实例。
 *              这个是在代码不知道具体对象是哪个，只有在程序运行的时候，去加载了配置文件才知道会创建哪个类的实例。所以以后要想修改类，只需要
 *              修改配置文件里的值就行。
 *      2. 注解：只是个标识，告诉解析器，我注解里有东西，你要通过反射机制去动态的给我处理。例如：创建对象，给对象赋值等。
 *      3. 注解是依赖反射来实现的。
 */

public class AnnoTest {

    public static void main(String[] args) throws Exception{
        // 反射开始，通过.calss拿到cat这个类的所有东西
        Class<Cat> catClass = Cat.class;

        // 要判断注解；注解其实就是个标识
        MyClass annotation = catClass.getAnnotation(MyClass.class);

        // 判断是否有类注解
        if (annotation!=null) {

            // 如果有myclass这个注解标识的话，就获取构造器，然后实例化一个对象
            Constructor<Cat> constructor = catClass.getConstructor(null);
            Cat cat = constructor.newInstance();

            // 开始解析字段的注解
            // 获取这个类所有的私有字段;catClass.getFields()这个拿到的是包括了继承的所有字段，不适用。
            Field[] declaredFields = catClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {

                // 判断字段是否有myvalue的注解
                MyValue annotation1 = declaredField.getAnnotation(MyValue.class);
                if (annotation1!=null) {

                    // 如果有myvalue注解，就把注解的值赋给字段
                    String typeName = declaredField.getType().getName();
                    String annoValue = annotation1.value();

                    // 暴力反射，能获取和设置私有属性
                    declaredField.setAccessible(true);

                    if (typeName.equals("java.lang.Integer")) {
                        int intValue = Integer.parseInt(annoValue);
//                        cat.setAge(intValue);
                        declaredField.set(cat, intValue);
                    }else{
                        declaredField.set(cat, annoValue);
                    }
                }else{
                    System.out.println(declaredField.getName() + "没有myvalue注解！！");
                }
            }

            System.out.println(cat);

        }else{
            System.out.println("没有myclass这个类注解！！");
        }
    }

}
